package net.ib.mtalk.ui.attachment.video;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import net.ib.mtalk.R;
import net.ib.mtalk.base.BaseActivity;
import net.ib.mtalk.constant.MTalkConstant;
import net.ib.mtalk.util.MTalkLogWriter;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.ImageButton;
import android.widget.Toast;

public class VideoRecordActivity extends BaseActivity implements SurfaceHolder.Callback {
	
	private VideoRecordManager videoRecordManager;

	private SurfaceView finder;
	private boolean isSurfaceOn = false;
	private SurfaceHolder lense;
	
	private ImageButton resetStartButton;
	private ImageButton cancelStopButton;
	private CheckBox checkQualityRecording;

	protected CompoundButton.OnCheckedChangeListener qualityCheckListener = new CompoundButton.OnCheckedChangeListener() {
		@Override
		public void onCheckedChanged(CompoundButton buttonView,	boolean isChecked) {
			videoRecordManager.setQualityRecording(isChecked);
			resetAction();
		}
	};

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		initUI();

		// wait for surfaceCreated()
	}

	@Override
	protected void onPause() {
		MTalkLogWriter.v(this.getClass()+".onPause() - STT");

		super.onPause();
		
		cancelAction();

		MTalkLogWriter.v(this.getClass()+".onPause() - STT");
	}

	@Override
	public void onResume() {
		MTalkLogWriter.v(this.getClass()+".onResume() - STT");

		super.onResume();
		if (isSurfaceOn == true) {
			resetAction();
		}

		MTalkLogWriter.v(this.getClass()+".onResume() - STT");
	}

	@Override
	public void onDestroy() {
		MTalkLogWriter.v(this.getClass()+".onDestroy() - STT");

		cancelAction();

		super.onDestroy();
		
		MTalkLogWriter.v(this.getClass()+".onDestroy() - END");
	}

	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		MTalkLogWriter.v(this.getClass()+".surfaceCreated() - STT");

		isSurfaceOn = true;
		resetAction();
		
		MTalkLogWriter.v(this.getClass()+".surfaceCreated() - END");
	}

	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width,
			int height) {
		// do nothing
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {
		MTalkLogWriter.v(this.getClass()+".surfaceDestroyed() - STT");

		isSurfaceOn = false;
		
		MTalkLogWriter.v(this.getClass()+".surfaceDestroyed() - END");
	}
	
	/**
	 * 변하지 않는 UI 요소들
	 */
	private void initUI() {
		setContentView(R.layout.layout_attachment_record_video);
		
		finder = (SurfaceView) findViewById(R.id.viewer_record_video);
		lense = finder.getHolder();
		lense.addCallback(this);
		lense.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

		resetStartButton = (ImageButton) findViewById(R.id.btn_reset_start_record_video);
		cancelStopButton = (ImageButton) findViewById(R.id.btn_cancel_stop_record_video);

		resetStartButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				resetStartAction();
			}
		});
		cancelStopButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				cancelStopAction();
			}
		});

		if(Build.VERSION.SDK_INT >= 8) {
			checkQualityRecording = (CheckBox) findViewById(R.id.check_quality_recording);
			checkQualityRecording.setVisibility(View.VISIBLE);
			checkQualityRecording.setOnCheckedChangeListener(qualityCheckListener);
		}
		
		resetStartButton.setClickable(false);
		cancelStopButton.setClickable(false);
	}

	/**
	 * @return 다음 녹화를 할 때 기록할 파일의 경로.
	 * 리턴 시점에 아직 파일은 만들어지지 않았고 중간 디렉토리는 만들어졌다.
	 */
	private String readyTargetFilePath() {
		try {
			String state = android.os.Environment.getExternalStorageState();
		    if(!state.equals(android.os.Environment.MEDIA_MOUNTED))  {
		        throw new IOException("SD Card is not mounted.  It is " + state + ".");
		    }
		} catch (IOException e) {
			MTalkLogWriter.e(e);
			return null;
		}
	    
		String path = MTalkConstant.MTALK_PATH + "/video";
		File directory = new File(path);
		if(!directory.exists()){
			directory.mkdirs();
		}
		if (!directory.exists() && !directory.mkdirs()) {
			try {
				throw new IOException("Path to file could not be created.");
			} catch (IOException e) {
				MTalkLogWriter.e(e);
			}
		}
		String dateString = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss-SSSZ").format(new Date());
		path += "/mnTalkVideo_" + dateString + ".mp4";

		return path;
	}

	/**
	 * 결과를 세팅하고 이 액티비티를 종료한다. 이 액티비티의 호출자에게는 결과의 주소가 담긴 인텐트를 반환한다.
	 * @param fileUrl 결과 파일의 주소
	 */
	private void submitResult(String fileUrl) {
		Intent intent = new Intent();
		intent.setData(Uri.parse(fileUrl));
		if (fileUrl == null) {
			setResult(RESULT_CANCELED, intent);
		} else {
			setResult(RESULT_OK, intent);
		}

		finish();
	}
	
	/**
	 * 매니저 상태를 리셋하고 촬영 대기 상태에 들어감
	 */
	private void resetAction() {
		try {
			if (videoRecordManager == null)
				videoRecordManager = new VideoRecordManager();
			
			videoRecordManager.resetRecorder(readyTargetFilePath(), lense, null);

			resetStartButton.setClickable(true);
			resetStartButton.setImageResource(R.drawable.btn_ic_video_record);
			cancelStopButton.setClickable(true);
			cancelStopButton.setImageResource(R.drawable.btn_ic_video_record_cancel);
		} catch (Exception e) {
			MTalkLogWriter.e(e);
		}
	}
	
	/**
	 * 녹화를 시작한 경우. Screen On 상태로 해둠.
	 */
	private void startAction() {
		try {
			videoRecordManager.startRecorder();
			getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

			resetStartButton.setClickable(true);
			resetStartButton.setImageResource(R.drawable.btn_ic_video_record_stop);
			cancelStopButton.setClickable(true);
			cancelStopButton.setImageResource(R.drawable.btn_ic_video_record_check);
		} catch(Exception e) {
			MTalkLogWriter.e(e);
			Toast.makeText(VideoRecordActivity.this, "Fail", Toast.LENGTH_SHORT).show();
		}
	}
	
	/**
	 * 리셋 대기 동작과 녹화 시작을 토글. 상호 전이함.
	 */
	private void resetStartAction() {
		if (videoRecordManager == null) {
			resetAction();
			return;
		}
		switch (videoRecordManager.getState()) {
		case READY_TO_START:
			startAction();
			break;
		case RECORDING:
			resetAction();
			break;
		case BEFORE_START:
		case TERMINATED:
		default:
			break;
		}
	}

	/**
	 * 녹화 종료 후 Flag제거
	 */
	private void stopAction() {
		try {
			submitResult(videoRecordManager.stopRecorder());
			getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

			resetStartButton.setClickable(false);
			resetStartButton.setImageResource(R.drawable.btn_ic_video_record_stop);
			cancelStopButton.setClickable(false);
			cancelStopButton.setImageResource(R.drawable.btn_ic_video_record_uncheck);
		} catch(Exception e) {
			MTalkLogWriter.e(e);
			Toast.makeText(VideoRecordActivity.this, "Fail", Toast.LENGTH_SHORT).show();
		}
	}
		
	private void cancelAction() {
		try {
			if (videoRecordManager == null)
				return;
			
			resetStartButton.setClickable(false);
			resetStartButton.setImageResource(R.drawable.btn_ic_video_record_stop);
			cancelStopButton.setClickable(false);
			cancelStopButton.setImageResource(R.drawable.btn_ic_video_record_uncheck);
			
			videoRecordManager.cancelRecorder();
			videoRecordManager = null;
		} catch(Exception e) {
			MTalkLogWriter.e(e);
			Toast.makeText(VideoRecordActivity.this, "Fail", Toast.LENGTH_SHORT).show();
		}
	}
	
	private void cancelStopAction() {
		if (videoRecordManager == null) {
			resetAction();
			return;
		}
		switch (videoRecordManager.getState()) {
		case READY_TO_START:
			// TODO 이 때 버튼의 표현이 누를 수 없는 것처럼 되는데 아무 동작을 안 해야 하는 것 아닌지?
			finish();
			break;
		case RECORDING:
			stopAction();
			break;
		case BEFORE_START:
		case TERMINATED:
		default:
			break;
		}
	}
	
}
